package me.gacl.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import me.gacl.utils.JdbcUtils;

/**
* @ClassName: TransactionDemo1
* @Description: 
* JDBC中使用事务来模似转帐 
    create table account(
        id int primary key auto_increment,
        name varchar(40),
        money float
    );
    insert into account(name,money) values('A',1000);
    insert into account(name,money) values('B',1000);
    insert into account(name,money) values('C',1000);
* @author: 孤傲苍狼
* @date: 2014-9-22 下午11:16:17
*
*/ 
public class TransactionDemo2Test {
	
    @After
    public void after() {
    	 System.out.println("after");
    }
    
    @Before
    public void before() {
        System.out.println("befor");
    }
    /**
    * @return 
     * @Method: testTransaction1
    * @Description: 模拟转账成功时的业务场景
    * @Anthor:孤傲苍狼
    *
    */ 
    @Test
    public void testTransaction1(){
    	 	Connection conn = null;
         PreparedStatement st = null;
         ResultSet rs = null;
         Savepoint sp = null;
         
         try {
        	 conn = JdbcUtils.getConnection();
        	 conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
        	 
        	 String sql1 = "update account set money=money-100 where name='A'";
             st = conn.prepareStatement(sql1);
             st.executeUpdate();
             
             //设置事务回滚点
             sp = conn.setSavepoint();
             
             String sql2 = "update account set money=money+100 where name='B'";
             st = conn.prepareStatement(sql2);
             st.executeUpdate();
             
           //程序执行到这里出现异常，后面的sql3语句执行将会中断
             int x = 1/0;
             
             String sql3 = "update account set money=money+100 where name='C'"; 
             st = conn.prepareStatement(sql3);
             st.executeUpdate();
             
             conn.commit();
			
		} catch (Exception e) {
			// TODO: handle exception
			 try {
	                /**
	                 * 我们在上面向数据库发送了3条update语句，
	                 * sql3语句由于程序出现异常导致无法正常执行，数据库事务而已无法正常提交，
	                 * 由于设置的事务回滚点是在sql1语句正常执行完成之后，sql2语句正常执行之前,
	                 * 那么通知数据库回滚事务时，不会回滚sql1执行的update操作
	                 * 只会回滚到sql2执行的update操作，也就是说，上面的三条update语句中，sql1这条语句的修改操作起作用了
	                 * sql2的修改操作由于事务回滚没有起作用，sql3由于程序异常没有机会执行
	                 */
	                conn.rollback(sp);//回滚到设置的事务回滚点
	                //回滚了要记得通知数据库提交事务
	                conn.commit();
	            } catch (SQLException e1) {
	                e1.printStackTrace();
	            }
	            e.printStackTrace();
		}finally {
			JdbcUtils.release(conn, st, rs);
		}
    }
    

}
